/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.rtx.base.impl;

import im.rtx.base.event.Event;
import im.rtx.base.event.EventListener;
import im.rtx.base.service.EventService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Project  : im.rtx.base.impl
 * Author   : solosky < solosky772@qq.com >
 * Created  : 2014/10/4
 * License  : Apache License 2.0
 */
@Service
public class EventServiceImpl implements EventService {
    private static final Logger LOG = LoggerFactory.getLogger(EventServiceImpl.class);
    /**Type => list<listener> **/
    private Map<String, List<EventListener>> lookup;
    public EventServiceImpl(){
        lookup = new HashMap<String, List<EventListener>>();
    }

    @Override
    public void register(String[] intrestedEvents, EventListener listener) {
        for(String type: intrestedEvents){
            List<EventListener> list = lookup.get(type);
            if(list == null){
                list = new ArrayList<EventListener>();
                lookup.put(type, list);
            }
            list.add(listener);
        }

    }

    @Override
    public void unregister(String[] intrestedEvents,
                           EventListener listener) {
        for(String type: intrestedEvents){
            List<EventListener> list = lookup.get(type);
            if(list != null){
                list.remove(listener);
            }
        }
    }

    @Override
    public void unregister(EventListener listener) {
        unregister(lookup.keySet().toArray(new String[0]), listener);
    }



    @Override
    public void broadcast(final Event event){
        if(EventQueue.isDispatchThread()){
            doBroadcast(event);
        }else{
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    doBroadcast(event);
                }
            });
        }
    }


    @Override
    public Event createEvent(String code, Object target) {
        Event event = new Event();
        event.setCode(code);
        event.setTarget(target);
        return event;
    }

    @Override
    public void createAndBroadcast(String code, Object target) {
        broadcast(createEvent(code, target));
    }

    private void doBroadcast(Event event){
        List<EventListener> list = lookup.get(event.getCode());
        LOG.debug("Broadcast Event: " + event.getCode()+", listeners: " + (list != null ? list.size(): 0));
        if(list != null && list.size() > 0){
            list = new ArrayList<EventListener>(list);
            for(EventListener listener: list){
                try {
                    listener.onEvent(event);
                } catch (Throwable e) {
                    LOG.warn("Broadcast Event Error!", e);
                }
            }
        }
    }
}
